module msync(
    input       clk,
    input       rst_n,
    input [2:0] sin,
    output reg  sout,
    output reg  valid
);

    reg  [5 :0] addr;
    reg  [5 :0] areg;
    reg  [31:0] sum  [62:0];
    reg  [2 :0] sreg [62:0];
    reg  [31:0] sumc;
    reg  [31:0] sums;
    reg  [31:0] count;
    reg         sflag;
    reg         cflag;
    reg         vflag;
    wire [1 :0] dreg;
    wire [1 :0] creg;
    wire [62:0] mreg;

    integer i;

    // 求绝对值
    assign dreg = sin[2] ? (~sin+1) : sin[1:0];
    assign creg = sreg[0][2] ? (~sreg[0]+1) : sreg[0][1:0];

    // M序列同步
    always @(posedge clk, negedge rst_n) begin
        if (!rst_n) begin
            addr <= 6'b0;
            areg <= 6'b0;
            sflag <= 1'b0;
            for(i=0; i<63; i=i+1)
            begin : sum_init
                sum[i] <= 32'd100;
            end
        end
        else begin
            if (addr<62) addr <= addr + 1'b1;
            else addr <= 6'b0;
            if (addr==0) begin
                for(i=0; i<63; i=i+1)
                begin : sum_rst
                    sum[i] <= 32'd100;
                end
            end
            else begin
                for(i=0; i<63; i=i+1)
                begin : sum_cal
                    if (sin[2]==mreg[i]) sum[i] <= sum[i] + dreg;
                    else sum[i] <= sum[i] - dreg;
                end
            end
            for(i=0; i<63; i=i+1)
            begin : sync_flag
                if ((addr==0) & (sum[i]>132) & (!sflag)) begin
                    areg <= i;
                    sflag <= 1'b1;
                end
            end
        end
    end

    //信息码同步
    always @(posedge clk, negedge sflag) begin
        if (!sflag) begin
            for(i=0; i<63; i=i+1)
            begin : sreg_init
                sreg[i] <= 3'b0;
            end
            sumc <= 32'd100;
            cflag <= 1'b0;
        end
        else begin
            sreg[62] <= sin;
            for(i=0; i<62; i=i+1)
            begin : sreg_shift
                sreg[i] <= sreg[i+1];
            end
            case ({sin[2]==mreg[areg], sreg[0][2]==mreg[areg]})
                2'b00 : sumc <= sumc - dreg + creg;
                2'b01 : sumc <= sumc - dreg - creg;
                2'b10 : sumc <= sumc + dreg + creg;
                2'b11 : sumc <= sumc + dreg - creg;
            endcase
            if ((sumc<68) & (!cflag)) cflag <= 1'b1;
        end
    end

    // 计算信息码
    always @(posedge clk, negedge cflag) begin
        if (!cflag) begin
            sout <= 1'b0;
            vflag <= 1'b0;
            valid <= 1'b0;
            sums <= 32'd100;
            count <= 32'b0;
        end
        else begin
            if (count<62) count <= count + 1'b1;
            else count <= 32'b0;
            if (count==0) sums <= 32'd100;
            else if (sin[2]==mreg[areg]) sums <= sums + dreg;
            else sums <= sums - dreg;
            if (count==0) begin
                vflag <= 1'b1;
                valid <= vflag;
                if (sums>100) sout <= 1'b1;
                else sout <= 1'b0;
            end
        end
    end

    // M序列存储
    mrom mrom(
        .address(addr),
        .clock(clk),
        .q(mreg)
    );

endmodule 